<template>
    <div class="box">
        <h3>组合式api【Composition Api】</h3>
        <p>组合式API采用常规js的流式代码方式进行功能开发,为了将变量方法等相关功能以一块代码区的方式进行展示</p>
        <hr>
        <h5>单文件组件的选项式组合式的定义规则</h5>
        <ul>
            <li>单选项式单文件组件
                <img src="@/index/assets/38.png" alt="" srcset="">
            </li>
            <li>单组合式单文件组件
                <img src="@/index/assets/39.png" alt="" srcset="">
            </li>
            <li>混合式单文件组件【不建议使用】
                <img src="@/index/assets/40.png" alt="" srcset="">
            </li>
        </ul>
        <hr>
        <h5>组合式api的使用语法</h5>
        <p>vue的模板语法使用规则不变，只有功能语法发生*定义方式变化*</p>
        <p>如果是混合式规则的 setup 方法中进行定义相关功能页面需要使用，必须通过 return 方式完成返回</p> 
        <ol>
            <li>响应式变量定义:通过vue提供的响应式变量构成方法 ref(默认值) 以js变量定义语法进行定义<br>
                响应式变量完成构建后会转换为一个固定的响应式对象，变量的值存在于该对象的 value中，js中需通过.value获取数据 <br>
                例如 <br>
                 import { ref } from "vue"; <br>
                 let msg = ref("字符串"); <br>
                 let arr = ref([1,2,3,4,5])
                <div>
                    msg：{{ msg }}
                    <input v-model="msg" type="text" />
                </div>
            </li>
            <li>方法定义: 直接以JS方式定义方法;使用规则在当前组合式语法范围内等效于JS <br>
                方法不再提供this的绑定到vue实例的操作;此时方法的this为当前组件定义的相关数据的集合对象，但不能调用实例方法或属性<br>
                <input type="button" value="showTip" @click="showTip()">
                <input type="button" value="restMsg" @click="restMsg()">
            </li>
            <li>vue模板元素的DOM获取:通过vue提供的加载方法 ref() 完成模板中定义ref属性的DOM元素加载 <br>
                例如 <br>   
                let divDom = ref(); <br>
                上述代码中变量名同时表示模板中ref的属性取值；ref()方法会在组合式api解析是自动完成DOM元素的加载 <br>
                被加载的DOM元素会作为 value取值定义于 ref() 构成响应式对象中 <br>
                <div ref="divDom">被加载的DOM</div>
                <input type="button" value="加载DOM" @click="printDivDom()">
            </li>
            <li>计算属性的定义:通过vue提供的 computed(计算属性配置) 完成定义  <br>
                <pre>
                例如：
                    import { computed } from "vue";
                    let info = ref("info");
                    // 只读定义
                    let cinfo = computed(function(){
                        return info.value + ".end";
                    })
                    // 可读可写
                    let cinfo = computed({
                        get(){
                            return info.value + ".end"
                        },
                        set(nv){
                            info.value = nv;
                        }
                    })
                </pre>
                <div>
                    cinfo:{{ cinfo }} 
                    <input v-model="cinfo" type="text" />
                </div>
            </li>
            <li>监视器的定义:通过vue提供的 watch() 函数完成定义【该函数的使用规则等通过实例方法$watch】<br>
                <pre>
                let unwatch = watch(source,callback,option)
                    + source:被监控的变量或者组合函数
                    + callback:变化时的回调函数
                    + option:{ deep:false,immediate:false }
                返回值 unwatch 方法，可以调用完成手动关闭监视的操作
                </pre>
                <div>text:{{ text }}</div>
                <input v-model="text" type="text" /><br><br>
                <div>user:{{ user }}</div>
                <input v-model="user.name" type="text" />
                <input type="button" value="重置user" @click="user={name:'jack'}">
                <input type="button" value="关闭user.name的监控" @click="unUserNameWatch()">
            </li>
        </ol>
    </div>
</template>

<script setup>
import { ref,computed,watch } from "vue";

let msg = ref("msg");

// function showTip(){
//     alert(1)
// }
const showTip = function(){
    // console.log(msg)
    console.log(this)
    console.log(this.$options)
    alert(msg.value)
}
const restMsg = function(){
    msg.value = "新msg"
}

let divDom = ref();
const printDivDom = function(){
    console.log(divDom.value)
}

let info = ref("info");
// let cinfo = computed(function(){
//     return info.value + ".end";
// })
let cinfo = computed({
    get(){
        return info.value + ".end"
    },
    set(nv){
        info.value = nv;
    }
})

let text = ref("text");
watch(text,function(nv,ov){
    console.log("text被修改:",nv,ov)
})
let user = ref({
    name:"tom"
});
// watch(user,function(nv,ov){
//     console.log("user被修改:",nv,ov)
// })
watch(user,function(nv,ov){
    console.log("user被修改:",nv,ov)
},{
    deep:true
})
let unUserNameWatch = watch(
    function(){
        return user.value.name
    },
    function(nv,ov){
        console.log("user.name被修改:",nv,ov)
    }
)
</script>

<!-- <script>
import { ref } from "vue";

export default {
    // 定义其它选项式代码

    // setup 为选项式内部的配置关键字，该方法内部代码采用组合式API
    setup:function(){
        // 定义组合式代码
        let msg = ref("msg");

        function showTip(){
            alert(1)
        }

        return { msg,showTip }
    }
}
</script> -->

<style lang="sass" scoped>

</style>